#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;

class CObject {
public:
    virtual string type() = 0;
    virtual string __str__() = 0;
};

class CInt : public CObject {
public:
    CInt(int i) : _i(i) {}
 
public:
    virtual string type() {
        return "<class 'int'>";
    }
    virtual string __str__() {
        return to_string(_i);
    }
private:
    int _i;
};

class CStr : public CObject {
public:
    CStr(const string& str) : _str(str) {}

public:
    virtual string type() {
        return "<class 'str'>";
    }

    virtual string __str__() {
        return "'" + _str + "'";
    }
private:
    string _str;
};

class CDict : public CObject {
public:
    CDict(const string& key, int val) {
        _dict[key] = val;
    }
    
public:
    virtual string type() {
        return "<class 'Dict'>";
    }

    virtual string __str__() {
        string result = "{";
        for (auto item: _dict) {
            result += "'" + item.first + "': " + to_string(item.second);
        }
        result += "}";

        return result;
    }
private:
    map <string, int> _dict;
};

typedef vector<CObject*> CObjectArray;


void type(CObject* p) {
    cout << p->type() << endl;
}

void ObjectPrint(const CObjectArray& oa) {
    
    string results = "[" ;
    
    for(auto o: oa) {
        type(o);
        results += o->__str__();
        results += ", ";
    }

    results = results.substr(0, results.size() - 2);
    results += "]";
    cout << results << endl;
}


int main(void) {
    CObjectArray objects;

    CInt* intObj = new CInt(10);
    objects.insert(objects.end(), intObj);

    CStr* strObj = new CStr("Jim");
    objects.insert(objects.end(), strObj);

    CDict* dictObj = new CDict("Age", 19);
    objects.insert(objects.end(), dictObj);

    ObjectPrint(objects);

    // Now to delete those object;
    for(auto& o: objects) {
        delete o;
    }

    objects.clear();

    return 0;
}